--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Commit c334a8ddd32a4e2f6beae4486ea876f40355bb67
Parents : d0b81de
Author : Mark Qvist <bc7291552be7a58f361522990465165c>
Signature : T66BB85Valid, signed by author
Date : 2026-07-20T03:10:56+02:00
Added custom map provider option
Changes
3 files changed, 48 insertions(+), 9 deletions(-)
Diff
diff --git a/sbapp/mapview/source.py b/sbapp/mapview/source.py
index 9790f10b..71eac37c 100644
--- a/sbapp/mapview/source.py
+++ b/sbapp/mapview/source.py
@@ -13,9 +13,10 @@ from mapview.utils import clamp
class MapSource:
mt_key = ""
- attribution_osm = '© OpenStreetMap contributors'
- attribution_ve = '© VirtualEarth'
- attribution_mt = '© MapTiler © OpenStreetMap contributors'
+ attribution_osm = "© OpenStreetMap contributors"
+ attribution_ve = "© VirtualEarth"
+ attribution_mt = "© MapTiler © OpenStreetMap contributors"
+ custom_1_url = "http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
providers = {}
@staticmethod
@@ -26,9 +27,11 @@ class MapSource:
"mt_outdoor": ("Outdoor", 0, 0, 19, "https://api.maptiler.com/maps/outdoor-v4/256/{z}/{x}/{y}.png?key="+MapSource.mt_key, MapSource.attribution_mt, 256),
"mt_hybrid": ("Hybrid", 0, 0, 19, "https://api.maptiler.com/maps/hybrid-v4/256/{z}/{x}/{y}.jpg?key="+MapSource.mt_key, MapSource.attribution_mt, 256),
"virtualearth": ("VirtualEarth", 0, 0, 19, "http://ecn.t3.tiles.virtualearth.net/tiles/a{q}.jpeg?g=1", MapSource.attribution_ve, 256),
- "opentopo": ("OpenTopo", 0, 0, 17, "https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png", MapSource.attribution_osm, 256),
- "testing": ("Testing", 0, 0, 19, "https://api.maptiler.com/maps/topo-v4/256/{z}/{x}/{y}.png?key="+MapSource.mt_key, MapSource.attribution_mt, 256),
+ "opentopo": ("OpenTopo", 0, 0, 19, "https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png", MapSource.attribution_osm, 256),
+ "atlas": ("Atlas", 0, 0, 19, "https://server.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer/tile/{z}/{y}/{x}", "© Esri", 256),
+ "custom_1": ("Custom 1", 0, 0, 19, MapSource.custom_1_url, "Custom Map", 256),
}
+ RNS.log(f"Providers\n{MapSource.providers}")
def __init__(self, name="Map", url="http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", cache_key=None,
min_zoom=0, max_zoom=19, tile_size=256, image_ext="png", attribution="© OpenStreetMap contributors",
diff --git a/sbapp/sideband/core.py b/sbapp/sideband/core.py
index 45bfbcb5..80a5e5f9 100644
--- a/sbapp/sideband/core.py
+++ b/sbapp/sideband/core.py
@@ -832,6 +832,7 @@ class SidebandCore():
if not "map_use_virtualearth" in self.config: self.config["map_use_virtualearth"] = True
if not "map_use_opentopo" in self.config: self.config["map_use_opentopo"] = True
if not "map_use_custom_1" in self.config: self.config["map_use_custom_1"] = False
+ if not "map_custom_1_url" in self.config: self.config["map_custom_1_url"] = ""
if not "discover_interfaces" in self.config: self.config["discover_interfaces"] = True
if not "map_storage_path" in self.config: self.config["map_storage_path"] = None
diff --git a/sbapp/ui/map.py b/sbapp/ui/map.py
index a53f0138..4bd623a8 100644
--- a/sbapp/ui/map.py
+++ b/sbapp/ui/map.py
@@ -58,6 +58,7 @@ class Map():
if not self.app.root.ids.screen_manager.has_screen("map_screen"):
MapSource.mt_key = self.DEFAULT_MT_API if not self.app.sideband.config["map_mt_api_key"] else self.app.sideband.config["map_mt_api_key"]
+ if self.app.sideband.config["map_custom_1_url"]: MapSource.custom_1_url = self.app.sideband.config["map_custom_1_url"]
MapSource.update_providers()
msource = self.get_source()
mzoom = self.app.sideband.config["map_zoom"]
@@ -283,6 +284,11 @@ class Map():
if self.app.sideband.config["map_use_hybrid"]: layers.append("mt_hybrid")
if self.app.sideband.config["map_use_opentopo"]: layers.append("opentopo")
if self.app.sideband.config["map_use_virtualearth"]: layers.append("virtualearth")
+ if self.app.sideband.config["map_use_custom_1"]:
+ url = self.app.sideband.config["map_custom_1_url"]
+ if url and (url.lower().startswith("http://") or url.lower().startswith("https://")):
+ layers.append("custom_1")
+
if len(layers) == 0: layers.append("osm")
return layers
@@ -382,6 +388,7 @@ class Map():
self.map_settings_screen.ids.map_use_hybrid.active = self.app.sideband.config["map_use_hybrid"]
self.map_settings_screen.ids.map_use_opentopo.active = self.app.sideband.config["map_use_opentopo"]
self.map_settings_screen.ids.map_use_virtualearth.active = self.app.sideband.config["map_use_virtualearth"]
+ self.map_settings_screen.ids.map_use_custom_1.active = self.app.sideband.config["map_use_custom_1"]
self.map_settings_screen.ids.map_storage_external.active = self.app.sideband.config["map_storage_external"]
self.map_settings_screen.ids.map_cluster.active = self.app.sideband.config["map_cluster"]
self.map_settings_screen.ids.map_interfaces.active = self.app.sideband.config["map_interfaces"]
@@ -399,11 +406,14 @@ class Map():
self.app.sideband.config["map_use_hybrid"] = self.map_settings_screen.ids.map_use_hybrid.active
self.app.sideband.config["map_use_opentopo"] = self.map_settings_screen.ids.map_use_opentopo.active
self.app.sideband.config["map_use_virtualearth"] = self.map_settings_screen.ids.map_use_virtualearth.active
+ self.app.sideband.config["map_use_custom_1"] = self.map_settings_screen.ids.map_use_custom_1.active
self.app.sideband.config["map_cluster"] = self.map_settings_screen.ids.map_cluster.active
self.app.sideband.config["map_interfaces"] = self.map_settings_screen.ids.map_interfaces.active
self.app.sideband.config["map_connection_maps"] = self.map_settings_screen.ids.map_connection_maps.active
self.app.sideband.config["map_relaxed_loading"] = self.map_settings_screen.ids.map_relaxed_loading.active
self.app.sideband.config["map_mt_api_key"] = str(self.map_settings_screen.ids.map_mt_api_key.text).strip()
+ self.app.sideband.config["map_custom_1_url"] = str(self.map_settings_screen.ids.map_custom_1_url.text).strip()
+ if self.app.sideband.config["map_custom_1_url"]: MapSource.custom_1_url = self.app.sideband.config["map_custom_1_url"]
MapSource.mt_key = self.DEFAULT_MT_API if not self.app.sideband.config["map_mt_api_key"] else self.app.sideband.config["map_mt_api_key"]
MapSource.update_providers()
self.app.sideband.save_configuration()
@@ -438,6 +448,7 @@ class Map():
self.map_settings_screen.ids.map_use_hybrid.bind(active=layers_toggle)
self.map_settings_screen.ids.map_use_opentopo.bind(active=layers_toggle)
self.map_settings_screen.ids.map_use_virtualearth.bind(active=layers_toggle)
+ self.map_settings_screen.ids.map_use_custom_1.bind(active=layers_toggle)
self.map_settings_screen.ids.map_storage_external.bind(active=external_toggle)
self.map_settings_screen.ids.map_cluster.bind(active=map_settings_save)
self.map_settings_screen.ids.map_interfaces.bind(active=map_settings_save)
@@ -446,6 +457,8 @@ class Map():
self.map_settings_screen.ids.map_mt_api_key.text = self.app.sideband.config["map_mt_api_key"]
self.map_settings_screen.ids.map_mt_api_key.bind(focus=map_settings_save)
+ self.map_settings_screen.ids.map_custom_1_url.text = self.app.sideband.config["map_custom_1_url"]
+ self.map_settings_screen.ids.map_custom_1_url.bind(focus=map_settings_save)
def settings_action(self, sender=None, direction="left"):
if not self.app.root.ids.screen_manager.has_screen("map_settings_screen"):
@@ -1074,6 +1087,22 @@ MDScreen:
pos_hint: {"center_y": 0.3}
active: False
+ MDBoxLayout:
+ orientation: "horizontal"
+ padding: [0,0,dp(24),0]
+ size_hint_y: None
+ height: dp(48)
+
+ MDLabel:
+ id: map_storage_external_label
+ text: "Use external storage path"
+ font_style: "H6"
+
+ MDSwitch:
+ id: map_storage_external
+ pos_hint: {"center_y": 0.3}
+ active: False
+
MDBoxLayout:
orientation: "horizontal"
padding: [0,0,dp(24),0]
@@ -1171,15 +1200,21 @@ MDScreen:
height: dp(48)
MDLabel:
- id: map_storage_external_label
- text: "Use external storage path"
+ text: "Custom Source"
font_style: "H6"
MDSwitch:
- id: map_storage_external
+ id: map_use_custom_1
pos_hint: {"center_y": 0.3}
active: False
+ MDTextField:
+ id: map_custom_1_url
+ hint_text: "http://domain.net/{z}/{x}/{y}.png"
+ text: ""
+ max_text_length: 512
+ font_size: dp(24)
+
MDLabel:
text: "•"
font_style: "H6"
@@ -1200,7 +1235,7 @@ MDScreen:
id: map_mt_api_key
hint_text: "Custom MapTiler API key"
text: ""
- max_text_length: 128
+ max_text_length: 256
font_size: dp(24)
"""
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────